﻿using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Security;
using System.Security.Principal;
namespace BEGDC.Utility.Security
{
    public class CryptionAPI
    {
        
        
        [DllImport("kernel32")]
        private static extern uint GetLastError();

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptAcquireContext(ref IntPtr phProv, string pszContainer, string pszProvider, int dwProvType, int dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptCreateHash(IntPtr hProv, int Algid,int hKey,int dwFlags, ref IntPtr  phHash);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, int dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptDeriveKey(IntPtr hProv, int Algid, int hBaseData, int dwFlags, ref IntPtr phKey);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptDestroyHash(IntPtr hHash);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptEncrypt(IntPtr hKey, IntPtr hHash, int Final,int dwFlags, byte[] pbData, ref int pdwDataLen,int dwBufLen);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptDestroyKey(IntPtr lHkey);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptReleaseContext(IntPtr hProv, int dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]
        private static extern int CryptDecrypt(IntPtr hKey, IntPtr hHash,int Final, int dwFlags, byte[] pbData, ref int pdwDataLen);

        private const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";

        private const int PROV_RSA_FULL = 1;

        private const int CRYPT_NEWKEYSET = 8;

        private const int PP_CONTAINER = 6;

        private const int AT_KEYEXCHANGE = 1;

        private const int AT_SIGNATURE = 2;

        private const int SIMPLEBLOB = 1;

        private const int ALG_CLASS_DATA_ENCRYPT = 24576;

        private const int ALG_CLASS_HASH = 32768;

        private const int ALG_TYPE_ANY = 0;

        private const int ALG_TYPE_BLOCK = 1536;

        private const int ALG_TYPE_STREAM = 2048;

        private const int ALG_SID_RC2 = 2;

        private const int ALG_SID_RC4 = 1;

        private const int ALG_SID_MD5 = 3;

        private const int CALG_MD5 = ((ALG_CLASS_HASH | ALG_TYPE_ANY) | ALG_SID_MD5);

        private const int CALG_RC2 = ((ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK) | ALG_SID_RC2);

        private const int CALG_RC4 = ((ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM) | ALG_SID_RC4);

        private const int CALG_DES = 26113;


        public static string Encrypt(string text, string key)
        {
            byte[] inputByteArray = Encoding.UTF8.GetBytes(text);
            byte[] keys = ASCIIEncoding.ASCII.GetBytes(key);

            int len = inputByteArray.Length;
            byte[] buffer = new byte[len * 2];

            int lenbuff = len * 2;

            if (lenbuff < 10)
                lenbuff = 12;

            inputByteArray.CopyTo(buffer, 0);


            if (false)
            {


                IntPtr hProv = IntPtr.Zero;

                string provider = MS_DEF_PROV;

                if (CryptAcquireContext(ref hProv, null, provider, PROV_RSA_FULL, 0) == 0)
                    return null;

                IntPtr hHash = IntPtr.Zero;

                if (CryptCreateHash(hProv, CALG_MD5, 0, 0, ref hHash) == 0)
                    return null;

                if (CryptHashData(hHash, keys, key.Length, 0) == 0)
                    return null;

                IntPtr hKey = IntPtr.Zero;
                if (CryptDeriveKey(hProv, CALG_DES, hHash.ToInt32(), 0, ref hKey) == 0)
                    return null;


                if (CryptEncrypt(hKey, IntPtr.Zero, 1, 0, buffer, ref len, lenbuff) == 0)
                    return null;

                CryptDestroyKey(hKey);

                CryptDestroyHash(hHash);

                CryptReleaseContext(hProv, 0);

                
            }

            return Convert.ToBase64String(buffer, 0, len+1);
        }

        public static string Decrypt(string text, string key)
        {
            
            byte[] inputByteArray = Convert.FromBase64String(text);
            byte[] keys = ASCIIEncoding.ASCII.GetBytes(key);

            int len = inputByteArray.Length - 1;

            int buflen = len * 2;
            if (buflen < 10)
                buflen = 12;

            byte[] buffer = new byte[buflen];

            inputByteArray.CopyTo(buffer, 0);

            if (false)
            {


                IntPtr hProv = IntPtr.Zero;

                string provider = MS_DEF_PROV;

                if (CryptAcquireContext(ref hProv, null, provider, PROV_RSA_FULL, 0) == 0)
                    return null;

                IntPtr hHash = IntPtr.Zero;

                if (CryptCreateHash(hProv, CALG_MD5, 0, 0, ref hHash) == 0)
                    return null;

                if (CryptHashData(hHash, keys, key.Length, 0) == 0)
                    return null;

                IntPtr hKey = IntPtr.Zero;
                if (CryptDeriveKey(hProv, CALG_DES, hHash.ToInt32(), 0, ref hKey) == 0)
                    return null;

                buffer[len] = 0;

                if (CryptDecrypt(hKey, IntPtr.Zero, 1, 0, buffer, ref len) == 0)
                    return null;

                CryptDestroyKey(hKey);

                CryptDestroyHash(hHash);

                CryptReleaseContext(hProv, 0);


                
            }
            return System.Text.Encoding.UTF8.GetString(buffer, 0, len);
        }

        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        WindowsImpersonationContext impersonationContext;

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern int LogonUser(String lpszUserName,
                                          String lpszDomain,
                                          String lpszPassword,
                                          int dwLogonType,
                                          int dwLogonProvider,
                                          ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
        public extern static int DuplicateToken(IntPtr hToken,
                                          int impersonationLevel,
                                          ref IntPtr hNewToken);


        public  bool impersonateValidUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
            LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    if (impersonationContext != null)
                        return true;
                    else
                        return false;
                }
                else
                    return false;
            }
            else
                return false;
        }
        public void undoImpersonation()
        {
            impersonationContext.Undo();
        } 


    }
}
